WebAssembly SIMD
chrome 84でorigin trial -> 91でshipping
wasm-feature-detectでチェックする
emcc -msimd128 -O3 foo.c -o foo.js
-msimd128
These optimizations can automatically transform loops that perform arithmetic operations on each iteration into equivalent loops that perform the same arithmetic operations on multiple inputs at a time using SIMD instructions
-msimd128をつけると、LLVM autovectorizersが-O2, -O3でデフォルトで有効になる
しかし、ベタに書いたコードでは最適な結果にならないので、
wasm_simd128.hで、Intrinsicsを使って期待通りコンパイルされるようにしないといけない code:cpp
void multiply_arrays(int* out, int* in_a, int* in_b, int size) {
for (int i = 0; i < size; i += 4) {
v128_t a = wasm_v128_load(&in_ai); v128_t b = wasm_v128_load(&in_bi); v128_t prod = wasm_i32x4_mul(a, b);
wasm_v128_store(&outi, prod); }
}
roundne-{neon, scalar, sse, sse2, sse41, wasmdimd} それぞれ実装がある
Rust
RUSTFLAGS="-C target-feature=+simd128" cargo build
iter.for_ezchを使うと最適な結果が得られる。C++のようにlow levelに書くこともできる
The motivation for this proposal is to introduce WebAssembly operations that map to commonly available SIMD instructions in hardware.
WebAssembly is extended with a new v128 value type and a number of new kinds of immediate operands used by the SIMD instructions.
f32x4, i16x8
512bitまでサポートするHWあるが、128bitが一般的。ポータブルにするためにこれを標準化
どれをサポートするか?
複数のmodern architecturesでサポートされている
パフォーマンスが向上すること
performance cliffsがある場合、最小化すること
widely used SIMD opsをmodern hardwareに近い形でマッピング
Intel, Armv7, v8のporable subset。SIMD.jsをベースに
SIMD has driven large speed ups in certain cases such as image manipulation, video encoding/decoding, machine learning, game engines and physics engines etc - with some of these use-cases not being usable without SIMD support, making SIMD support for the web platform essential for achieving near-native speed with certain native applications.
画像処理とかはこれがないと実現が難しい
JSからは、memoryを直接操作できる
がv128の型自体はjSから扱えない。TypeError
opcode
Example
Constructing SIMD values
v128.const(imm: ImmByte[16]) -> v128
16個のByte列からv128型にする
v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
i8x16.splat(x: i32) -> v128
i32をコピーしてi8x16のv128にする
Accessing lanes
i8x16.extract_lane_s(a: v128, imm: ImmLaneIdx16) -> i32
code:py
def S.extract_lane(a, i):
arithmetic
add, sub, dot, ...
max, avg, abs
bit
shift
and, or
popcount
comparisions
eq, ne, lt
load and store
v128.load(m: memarg) -> v128
memarg = {offset, align}
16byte loadする